package ictbk.ttmk51.grapro.app.utils;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;

import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.provider.ContactsContract;
import android.provider.ContactsContract.RawContacts;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.util.Log;
import ictbk.ttmk51.grapro.app.safephonebook.Address;
import ictbk.ttmk51.grapro.app.safephonebook.ClientContact;
import ictbk.ttmk51.grapro.app.safephonebook.Contact;
import ictbk.ttmk51.grapro.app.safephonebook.Email;
import ictbk.ttmk51.grapro.app.safephonebook.IM;
import ictbk.ttmk51.grapro.app.safephonebook.Organization;
import ictbk.ttmk51.grapro.app.safephonebook.Phone;

/**
 * reference from:
 * http://lampwww.epfl.ch/~linuxsoft/android/android-m3-rc37a/docs
 * /devel/data/contentproviders.html#creatingacontentprovider
 * http://www.higherpass.com/Android/Tutorials/Working-With-Android-Contacts/
 * 
 * @author Nguyen Van Dang
 * 
 */
public class ContactProvider {
	private Cursor			cur;
	private ContentResolver	cr;

	public ContactProvider(ContentResolver cr, Cursor cur) {
		this.cr = cr;
		this.cur = cur;
	}

	public ContactProvider() {
	};

	public Cursor getCur() {
		return cur;
	}

	public void setCur(Cursor cur) {
		this.cur = cur;
	}

	public ContentResolver getCr() {
		return cr;
	}

	public void setCr(ContentResolver cr) {
		this.cr = cr;
	}

	/**
	 * Auto get info contact to show on list view. Example: display name, phone
	 * number, type. Key: "DisplayName" to get value to display on top every
	 * cell in list Key: "BottomRightInfo" to get value phone number or email...
	 * & "BottomLeftInfo" to get value type
	 * 
	 * @param contact
	 * @return
	 */
	public HashMap<String, String> getContactInfoToShow(Contact contact) {
		HashMap<String, String> info = new HashMap<String, String>();
		if (contact == null) {
			return info;
		}
		String displayName = contact.getDisplayName();
		if (displayName != null) {
			if (displayName.trim().equals("")) {
				info.put("DisplayName", "(Unknow)");
			} else {
				info.put("DisplayName", displayName);
			}
		} else {
			info.put("DisplayName", "(Unknow)");
		}
		ArrayList<Phone> phones = contact.getPhone();
		if (phones != null && !phones.isEmpty()) {
			for (Phone phone : phones) {
				if (!phone.getNumber().trim().equals("")) {
					info.put("BottomRightInfo", phone.getNumber());
					info.put("BottomLeftInfo", phone.getTypeName());
					return info;
				}
			}
		}

		ArrayList<Email> emails = contact.getEmail();
		if (emails != null && !emails.isEmpty())
			for (Email email : emails) {
				if (!email.getAddress().trim().equals("")) {
					info.put("BottomRightInfo", email.getAddress());
					info.put("BottomLeftInfo", email.getTypeName());
					return info;
				}
			}
		ArrayList<IM> ims = contact.getImAddresses();
		if (ims != null && !ims.isEmpty()) {
			for (IM im : ims) {
				if (!im.getName().trim().equals("")) {
					info.put("BottomRightInfo", im.getName());
					info.put("BottomLeftInfo", im.getTypeName());
					return info;
				}
			}
		}
		ArrayList<Organization> organizations = contact.getOrganization();
		if (organizations != null && !organizations.isEmpty())
			for (Organization organization : organizations) {
				if (!organization.getOrganization().trim().equals("")) {
					info.put("BottomRightInfo", organization.getOrganization());
					info.put("BottomLeftInfo", organization.getTypeName());
					return info;
				}
			}

		return info;
	}

	public int deleteContactWithID(String ID) {
		Uri uri = Uri.parse("content://contacts/people");
		Log.i("Delete contac with ID", uri.toString());
		int rowsDeleted = cr.delete(uri, "_ID = " + ID, null);
		return rowsDeleted;
	}

	public int deleteContactWithName(String name) {
		Uri uri = Uri.parse("content://contacts/people");
		int rowsDeleted = cr.delete(uri, "display_name like '" + name + "'", null);
		return rowsDeleted;
	}

	public int deleteContactToEnd() {
		Uri uri = Uri.parse("content://contacts/people");
		int rowsDeleted = cr.delete(uri, null, null);
		return rowsDeleted;
	}

	/**
	 * This method useful to optimated memory.
	 * 
	 * @return
	 */
	public ArrayList<ClientContact> readBaseContactInfo() {
		ArrayList<ClientContact> contacts = new ArrayList<ClientContact>();
		String id;
		Log.i("All of contact to read", cur.getCount() + "");
		if (this.cur.getCount() > 0) {
			int i = 0;
			while (i < cur.getCount()) {
				if (cur.moveToPosition(i)) {
					ClientContact c = new ClientContact();
					id = cur.getString(cur.getColumnIndex(ContactsContract.Contacts._ID));
					c.setId(id);
					String name = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
					c.setDisplayName(name);

					Log.i("readBaseContactInfo", "-------------------" + c.getDisplayName() + "----------------------");

					// read Bitmap
					Uri uri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, Long.parseLong(id));
					InputStream input = ContactsContract.Contacts.openContactPhotoInputStream(cr, uri);
					Bitmap contactPhoto = BitmapFactory.decodeStream(input);
					c.setBitmap(contactPhoto);
					c.setPhone(this.getFirstPhoneNumber(id));
					if (c.getPhone().isEmpty()) {
						c.setEmail(this.getFirstEmailAddresse(id));
						if (c.getEmail().isEmpty()) {
							c.setImAddresses(this.getFirstIM(id));
							if (c.getImAddresses().isEmpty()) {
								c.setAddresses(getFirstContactAddresse(id));
								if (c.getAddresses().isEmpty()) {
									c.setOrganization(this.getContactOrg(id));
								}
							}
						}
					}
					contacts.add(c);
					i++;
				} else {
					Log.e("ERROR at method readBaseContactInfo", "cause: cannot move cursor to position " + i, new Exception("cursor move exception"));
				}
			}
		}
		if (cur.getCount() != contacts.size())
			Log.e("ERROR", "before read contact: " + cur.getCount() + ". after read contact: " + contacts.size(), new Exception("cursor move exception"));

		return contacts;
	}

	public Map<Character, LinkedList<ClientContact>> readBaseContactInfo0() {
		Map<Character, LinkedList<ClientContact>> sections = new HashMap<Character, LinkedList<ClientContact>>();

		String id;
		Log.i("All of contact to read", cur.getCount() + "");
		if (this.cur.getCount() > 0) {
			int i = 0;
			while (i < cur.getCount()) {
				if (cur.moveToPosition(i)) {
					ClientContact c = new ClientContact();
					id = cur.getString(cur.getColumnIndex(ContactsContract.Contacts._ID));
					c.setId(id);
					String name = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));

					c.setDisplayName(name);

				//	Log.i("readBaseContactInfo", "-------------------" + c.getDisplayName() + "----------------------");

					// read Bitmap
					Uri uri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, Long.parseLong(id));
					InputStream input = ContactsContract.Contacts.openContactPhotoInputStream(cr, uri);
					Bitmap contactPhoto = BitmapFactory.decodeStream(input);
					c.setBitmap(contactPhoto);
					c.setPhone(this.getFirstPhoneNumber(id));
					if (c.getPhone().isEmpty()) {
						c.setEmail(this.getFirstEmailAddresse(id));
						if (c.getEmail().isEmpty()) {
							c.setImAddresses(this.getFirstIM(id));
							if (c.getImAddresses().isEmpty()) {
								c.setAddresses(getFirstContactAddresse(id));
								if (c.getAddresses().isEmpty()) {
									c.setOrganization(this.getContactOrg(id));
								}
							}
						}
					}
					if (!name.equals("")) {
						char firstChar = name.charAt(0);
						if (sections.get(firstChar) == null) {
							LinkedList<ClientContact> contacts = new LinkedList<ClientContact>();
							contacts.add(c);
							sections.put(firstChar, contacts);
						} else {
							LinkedList<ClientContact> contacts = sections.get(firstChar);
							contacts.add(c);
						}
					}
					// contacts.add(c);
					i++;
				} else {
					Log.e("ERROR at method readBaseContactInfo", "cause: cannot move cursor to position " + i, new Exception("cursor move exception"));
				}
			}
		}

		return sections;
	}

	// Get Contact List
	public ArrayList<ClientContact> readFullClientContactInfo() {
		ArrayList<ClientContact> contacts = new ArrayList<ClientContact>();
		String id;
		Log.i("All of contact to read", cur.getCount() + "");
		if (this.cur.getCount() > 0) {
			int i = 0;
			while (i < cur.getCount()) {
				if (cur.moveToPosition(i)) {
					ClientContact c = new ClientContact();
					id = cur.getString(cur.getColumnIndex(ContactsContract.Contacts._ID));
					Log.i("ContactsContract.Contacts._ID", "" + ContactsContract.Contacts._ID);
					c.setId(id);
					c.setDisplayName(cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)));
					Log.i("Read Contact - ContactsContract.Contacts.DISPLAY_NAME", ContactsContract.Contacts.DISPLAY_NAME);
					// read Bitmap
					Uri uri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, Long.parseLong(id));
					InputStream input = ContactsContract.Contacts.openContactPhotoInputStream(cr, uri);
					Bitmap contactPhoto = BitmapFactory.decodeStream(input);
					c.setBitmap(contactPhoto);
					c.setPhone(this.getPhoneNumbers(id));
					c.setEmail(this.getEmailAddresses(id));
					c.setNotes(this.getContactNotes(id));
					c.setAddresses(this.getContactAddresses(id));
					c.setImAddresses(this.getIM(id));
					c.setOrganization(this.getContactOrg(id));
					contacts.add(c);
					i++;
				} else {
					Log.e("ERROR at method readFullContactInfo", "cause: cannot move cursor to position " + i, new Exception("cursor move exception"));
				}
			}
		}
		if (cur.getCount() != contacts.size())
			Log.e("ERROR", "before read contact: " + cur.getCount() + ". after read contact: " + contacts.size(), new Exception("cursor move exception"));

		return contacts;
	}

	public ArrayList<Contact> readFullContactInfo() {
		ArrayList<Contact> contacts = new ArrayList<Contact>();
		String id;
		Log.i("All of contact to read", cur.getCount() + "");
		if (this.cur.getCount() > 0) {
			int i = 0;
			while (i < cur.getCount()) {
				if (cur.moveToPosition(i)) {
					Contact c = new Contact();
					id = cur.getString(cur.getColumnIndex(ContactsContract.Contacts._ID));
					//When user backup contact, Id will not important. Because, when they restore, that contact will be add with new ID
					c.setDisplayName(cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)));
					Log.i("Read Contact", "-------------------" + c.getDisplayName() + "----------------------");
					
//					// read Bitmap
					Uri uri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, Long.parseLong(id));
					InputStream input = ContactsContract.Contacts.openContactPhotoInputStream(cr, uri);
					Bitmap contactPhoto = BitmapFactory.decodeStream(input);
					if(contactPhoto != null){
						Log.i("Oh, có ảnh avatar cơ à", "Chuẩn không cần chỉnh");
						String stringPhoto = BitmapStringBase64.BitmaptoStringBase64(contactPhoto);
						Log.i("String Photo", stringPhoto);
						c.setStringPhoto(stringPhoto);
					}else{
						Log.i("á à không có ảnh avatar", "hix hix hix, Sorry!!!");
					}
					
					c.setPhone(this.getPhoneNumbers(id));
					c.setEmail(this.getEmailAddresses(id));
					c.setNotes(this.getContactNotes(id));
					c.setAddresses(this.getContactAddresses(id));
					c.setImAddresses(this.getIM(id));
					c.setOrganization(this.getContactOrg(id));
					contacts.add(c);
					i++;
				} else {
					Log.e("ERROR at method readFullContactInfo", "cause: cannot move cursor to position " + i, new Exception("cursor move exception"));
				}
			}
		}
		if (cur.getCount() != contacts.size())
			Log.e("ERROR", "before read contact: " + cur.getCount() + ". after read contact: " + contacts.size(), new Exception("cursor move exception"));

		return contacts;
	}

	public int findContactWithName(String name) {
		cur = cr.query(Uri.parse("content://contacts/people"), null, "name like ?", new String[] { name }, null);
		return cur.getCount();
	}

	/**
	 * Update a new contact
	 * 
	 * @param contact
	 *            new contact to update
	 * @param id
	 *            old contact's id
	 */
	// public void updateContact(Contact contact, String id){
	// ContentValues values = new ContentValues();
	// values.put("display_name", contact.getDisplayName());
	// values.put("display_name", contact.getDisplayName());
	//		
	// cr.update(Uri.parse("content://com.android.contacts/contacts"), values,
	// "_id = ?", new String[]{id});
	// }

	public ClientContact readContact(String id) {
		cur = cr.query(Uri.parse("content://contacts/people"), null, "_id = ?", new String[] { id }, null);
		Log.i("Count", "" + cur.getCount());
		if (cur.getCount() == 0) {
			return null;
		}
		ClientContact c = new ClientContact();
		cur.moveToPosition(0);// So only have 1 element
		c.setDisplayName(cur.getString(cur.getColumnIndex("display_name")));
		c.setId(id);
		// read Bitmap
		Uri uri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, Long.parseLong(id));
		InputStream input = ContactsContract.Contacts.openContactPhotoInputStream(cr, uri);
		Bitmap contactPhoto = BitmapFactory.decodeStream(input);
		c.setBitmap(contactPhoto);
		c.setAddresses(getContactAddresses(id));
		c.setEmail(getEmailAddresses(id));
		c.setPhone(getPhoneNumbers(id));
		c.setImAddresses(getIM(id));
		c.setOrganization(getContactOrg(id));
		c.setNotes(getContactNotes(id));
		return c;
	}

	public ArrayList<Phone> getPhoneNumbers(String id) {
		ArrayList<Phone> phones = new ArrayList<Phone>();

		Cursor pCur = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?", new String[] { id }, null);
		Log.i("phone count", "" + pCur.getCount());
		int i = 0;
		while (i < pCur.getCount()) {
			if (pCur.moveToPosition(i)) {
				Phone p = new Phone(pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)), Integer.parseInt(pCur.getString(pCur
					.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE))));
				phones.add(p);
				i++;
			} else {
				Log.e("ERROR at method getPhoneNumbers", "cause: cannot move cursor to position " + i, new Exception("cursor move exception"));
			}
		}
		pCur.close();
		return phones;
	}
	
	public ArrayList<Phone> getFirstPhoneNumber(String id) {
		ArrayList<Phone> phones = new ArrayList<Phone>();

		Cursor pCur = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?", new String[] { id }, null);
		Log.i("phone count", "" + pCur.getCount());
		int i = 0;
		while (i < pCur.getCount()) {
			if (pCur.moveToPosition(i)) {
				Phone p = new Phone(pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)), Integer.parseInt(pCur.getString(pCur
					.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE))));
				phones.add(p);
				i++;
				break;
			} else {
				Log.e("ERROR at method getPhoneNumbers", "cause: cannot move cursor to position " + i, new Exception("cursor move exception"));
			}
		}
		pCur.close();
		return phones;
	}

	public ArrayList<Email> getEmailAddresses(String id) {
		ArrayList<Email> emails = new ArrayList<Email>();

		Cursor emailCur = this.cr.query(ContactsContract.CommonDataKinds.Email.CONTENT_URI, null, ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = ?", new String[] { id }, null);
		int i = 0;
		while (i < emailCur.getCount()) {
			if (emailCur.moveToPosition(i)) {
				// This would allow you get several email addresses
				String strEmailType = emailCur.getString(emailCur.getColumnIndex(ContactsContract.CommonDataKinds.Email.TYPE));
				int intEmailType = strEmailType == null ? -1 : Integer.parseInt(strEmailType);
				Email e = new Email(emailCur.getString(emailCur.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA)), intEmailType);
				emails.add(e);
				i++;
			} else {
				Log.e("ERROR at method getEmailAddresses", "cause: cannot move cursor to position " + i, new Exception("cursor move exception"));
			}
		}
		emailCur.close();
		return emails;
	}

	public ArrayList<Email> getFirstEmailAddresse(String id) {
		ArrayList<Email> emails = new ArrayList<Email>();

		Cursor emailCur = this.cr.query(ContactsContract.CommonDataKinds.Email.CONTENT_URI, null, ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = ?", new String[] { id }, null);
		int i = 0;
		while (i < emailCur.getCount()) {
			if (emailCur.moveToPosition(i)) {
				// This would allow you get several email addresses
				String strEmailType = emailCur.getString(emailCur.getColumnIndex(ContactsContract.CommonDataKinds.Email.TYPE));
				int intEmailType = strEmailType == null ? -1 : Integer.parseInt(strEmailType);
				Email e = new Email(emailCur.getString(emailCur.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA)), intEmailType);
				emails.add(e);
				i++;
				break;
			} else {
				Log.e("ERROR at method getEmailAddresses", "cause: cannot move cursor to position " + i, new Exception("cursor move exception"));
			}
		}
		emailCur.close();
		return emails;
	}

	public ArrayList<String> getContactNotes(String id) {
		ArrayList<String> notes = new ArrayList<String>();
		String where = ContactsContract.Data.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?";
		String[] whereParameters = new String[] { id, ContactsContract.CommonDataKinds.Note.CONTENT_ITEM_TYPE };
		Cursor noteCur = this.cr.query(ContactsContract.Data.CONTENT_URI, null, where, whereParameters, null);
		int i = 0;
		while (i < noteCur.getCount()) {
			if (noteCur.moveToPosition(i)) {
				String note = noteCur.getString(noteCur.getColumnIndex(ContactsContract.CommonDataKinds.Note.NOTE));
				if (note.length() > 0) {
					notes.add(note);
				}
				i++;
			} else {
				Log.e("ERROR at method getContactNotes", "cause: cannot move cursor to position " + i, new Exception("cursor move exception"));
			}
		}
		noteCur.close();
		return notes;
	}

	public ArrayList<String> getFirstContactNote(String id) {
		ArrayList<String> notes = new ArrayList<String>();
		String where = ContactsContract.Data.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?";
		String[] whereParameters = new String[] { id, ContactsContract.CommonDataKinds.Note.CONTENT_ITEM_TYPE };
		Cursor noteCur = this.cr.query(ContactsContract.Data.CONTENT_URI, null, where, whereParameters, null);
		int i = 0;
		while (i < noteCur.getCount()) {
			if (noteCur.moveToPosition(i)) {
				String note = noteCur.getString(noteCur.getColumnIndex(ContactsContract.CommonDataKinds.Note.NOTE));
				if (note.length() > 0) {
					notes.add(note);
				}
				i++;
				break;
			} else {
				Log.e("ERROR at method getContactNotes", "cause: cannot move cursor to position " + i, new Exception("cursor move exception"));
			}
		}
		noteCur.close();
		return notes;
	}

	public ArrayList<Address> getContactAddresses(String id) {
		ArrayList<Address> addrList = new ArrayList<Address>();

		String where = ContactsContract.Data.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?";
		String[] whereParameters = new String[] { id, ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE };

		Cursor addrCur = this.cr.query(ContactsContract.Data.CONTENT_URI, null, where, whereParameters, null);
		int i = 0;
		while (i < addrCur.getCount()) {
			if (addrCur.moveToPosition(i)) {
				String poBox = addrCur.getString(addrCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.POBOX));
				String street = addrCur.getString(addrCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.STREET));
				String city = addrCur.getString(addrCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.CITY));
				String state = addrCur.getString(addrCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.REGION));
				String postalCode = addrCur.getString(addrCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.POSTCODE));
				String country = addrCur.getString(addrCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY));
				int type = Integer.parseInt(addrCur.getString(addrCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.TYPE)));
				Address a = new Address(poBox, street, city, state, postalCode, country, type);
				addrList.add(a);
				i++;
			} else {
				Log.e("ERROR at method getContactAddresses", "cause: cannot move cursor to position " + i, new Exception("cursor move exception"));
			}
		}
		addrCur.close();
		return addrList;
	}

	public ArrayList<Address> getFirstContactAddresse(String id) {
		ArrayList<Address> addrList = new ArrayList<Address>();

		String where = ContactsContract.Data.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?";
		String[] whereParameters = new String[] { id, ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE };

		Cursor addrCur = this.cr.query(ContactsContract.Data.CONTENT_URI, null, where, whereParameters, null);
		int i = 0;
		while (i < addrCur.getCount()) {
			if (addrCur.moveToPosition(i)) {
				String poBox = addrCur.getString(addrCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.POBOX));
				String street = addrCur.getString(addrCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.STREET));
				String city = addrCur.getString(addrCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.CITY));
				String state = addrCur.getString(addrCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.REGION));
				String postalCode = addrCur.getString(addrCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.POSTCODE));
				String country = addrCur.getString(addrCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY));
				int type = Integer.parseInt(addrCur.getString(addrCur.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.TYPE)));
				Address a = new Address(poBox, street, city, state, postalCode, country, type);
				addrList.add(a);
				i++;
				break;
			} else {
				Log.e("ERROR at method getContactAddresses", "cause: cannot move cursor to position " + i, new Exception("cursor move exception"));
			}
		}
		addrCur.close();
		return addrList;
	}

	public ArrayList<IM> getIM(String id) {
		ArrayList<IM> imList = new ArrayList<IM>();
		String where = ContactsContract.Data.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?";
		String[] whereParameters = new String[] { id, ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE };

		Cursor imCur = this.cr.query(ContactsContract.Data.CONTENT_URI, null, where, whereParameters, null);
		int i = 0;
		while (i < imCur.getCount()) {
			if (imCur.moveToPosition(i)) {
				String imName = imCur.getString(imCur.getColumnIndex(ContactsContract.CommonDataKinds.Im.DATA));
				int imType = Integer.parseInt(imCur.getString(imCur.getColumnIndex(ContactsContract.CommonDataKinds.Im.PROTOCOL)));
				IM im = new IM(imName, imType);
				imList.add(im);
				i++;
			} else {
				Log.e("ERROR at method getIM", "cause: cannot move cursor to position " + i, new Exception("cursor move exception"));
			}
		}
		imCur.close();
		return imList;
	}

	public ArrayList<IM> getFirstIM(String id) {
		ArrayList<IM> imList = new ArrayList<IM>();
		String where = ContactsContract.Data.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?";
		String[] whereParameters = new String[] { id, ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE };

		Cursor imCur = this.cr.query(ContactsContract.Data.CONTENT_URI, null, where, whereParameters, null);
		int i = 0;
		while (i < imCur.getCount()) {
			if (imCur.moveToPosition(i)) {
				String imName = imCur.getString(imCur.getColumnIndex(ContactsContract.CommonDataKinds.Im.DATA));
				int imType = Integer.parseInt(imCur.getString(imCur.getColumnIndex(ContactsContract.CommonDataKinds.Im.PROTOCOL)));
				IM im = new IM(imName, imType);
				imList.add(im);
				i++;
				break;
			} else {
				Log.e("ERROR at method getIM", "cause: cannot move cursor to position " + i, new Exception("cursor move exception"));
			}
		}
		imCur.close();
		return imList;
	}

	public ArrayList<Organization> getContactOrg(String id) {
		ArrayList<Organization> orgs = new ArrayList<Organization>();
		String where = ContactsContract.Data.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?";
		String[] whereParameters = new String[] { id, ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE };

		Cursor orgCur = this.cr.query(ContactsContract.Data.CONTENT_URI, null, where, whereParameters, null);
		int i = 0;
		while (i < orgCur.getCount()) {
			if (orgCur.moveToPosition(i)) {
				String orgName = orgCur.getString(orgCur.getColumnIndex(ContactsContract.CommonDataKinds.Organization.DATA));
				String title = orgCur.getString(orgCur.getColumnIndex(ContactsContract.CommonDataKinds.Organization.TITLE));
				int type = Integer.parseInt(orgCur.getString(orgCur.getColumnIndex(ContactsContract.CommonDataKinds.Organization.TYPE)));
				if (orgName.length() > 0) {
					Organization orga = new Organization(orgName, title, type);
					orgs.add(orga);
				}
				i++;
			} else {
				Log.e("ERROR at method getContactOrg", "cause: cannot move cursor to position " + i, new Exception("cursor move exception"));
			}
		}
		orgCur.close();
		return orgs;
	}

	public ArrayList<Organization> getFirstContactOrg(String id) {
		ArrayList<Organization> orgs = new ArrayList<Organization>();
		String where = ContactsContract.Data.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?";
		String[] whereParameters = new String[] { id, ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE };

		Cursor orgCur = this.cr.query(ContactsContract.Data.CONTENT_URI, null, where, whereParameters, null);
		int i = 0;
		while (i < orgCur.getCount()) {
			if (orgCur.moveToPosition(i)) {
				String orgName = orgCur.getString(orgCur.getColumnIndex(ContactsContract.CommonDataKinds.Organization.DATA));
				String title = orgCur.getString(orgCur.getColumnIndex(ContactsContract.CommonDataKinds.Organization.TITLE));
				int type = Integer.parseInt(orgCur.getString(orgCur.getColumnIndex(ContactsContract.CommonDataKinds.Organization.TYPE)));
				if (orgName.length() > 0) {
					Organization orga = new Organization(orgName, title, type);
					orgs.add(orga);
				}
				i++;
				break;
			} else {
				Log.e("ERROR at method getContactOrg", "cause: cannot move cursor to position " + i, new Exception("cursor move exception"));
			}
		}
		orgCur.close();
		return orgs;
	}

	@SuppressWarnings("deprecation")
	public void writeContact(Contact contact) {
		if (contact == null)
			return;
		Log.i("Writing contact", "_________________________" + contact.getDisplayName() + "______________________");
		ContentValues values = new ContentValues();
		values.put(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME, contact.getDisplayName());
		Uri rawContactUri = cr.insert(RawContacts.CONTENT_URI, values);
		long rawContactId = ContentUris.parseId(rawContactUri);

		values.clear();
		values.put(ContactsContract.Data.RAW_CONTACT_ID, rawContactId);
		values.put(ContactsContract.Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
		values.put(StructuredName.DISPLAY_NAME, contact.getDisplayName());
		cr.insert(ContactsContract.Data.CONTENT_URI, values);
		
		//insert Photo Contact (new)
		if(contact.getStringPhoto() != null){
			Uri photoUri = Uri.withAppendedPath(rawContactUri, ContactsContract.Contacts.Data.CONTENT_DIRECTORY);
			values.clear();
			values.put(ContactsContract.Data.IS_SUPER_PRIMARY, 1);
			values.put(ContactsContract.CommonDataKinds.Photo.PHOTO, BitmapStringBase64.StringBase64toBitmap(contact.getStringPhoto()));
			values.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE);
			cr.insert(photoUri, values);
		}
		
		Uri phoneUri = null;
		Uri emailUri = null;
		Uri addressUri = null;
		Uri imUri = null;
		Uri orgUri = null;
		Uri noteUri = null;

		if (contact.getPhone() != null) {
			Log.i("Phone size", "" + contact.getPhone().size());
			for (Phone aPhone : contact.getPhone()) {
				phoneUri = Uri.withAppendedPath(rawContactUri, ContactsContract.Contacts.Data.CONTENT_DIRECTORY);
				values.clear();
				values.put(ContactsContract.CommonDataKinds.Phone.TYPE, aPhone.getType());
				values.put(ContactsContract.CommonDataKinds.Phone.IS_SUPER_PRIMARY, 1);
				values.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE);
				values.put(ContactsContract.CommonDataKinds.Phone.NUMBER, aPhone.getNumber());
				cr.insert(phoneUri, values);
			}
		}
		if (contact.getEmail() != null) {
			Log.i("Email size", "" + contact.getEmail().size());
			for (Email aEmail : contact.getEmail()) {
				emailUri = Uri.withAppendedPath(rawContactUri, ContactsContract.Contacts.Data.CONTENT_DIRECTORY);

				values.clear();
				values.put(ContactsContract.CommonDataKinds.Email.TYPE, aEmail.getType());
				values.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE);
				values.put(ContactsContract.CommonDataKinds.Email.DATA, aEmail.getAddress());
				cr.insert(emailUri, values);
			}
		}
		if (contact.getNotes() != null) {
			Log.i("Notes size", "" + contact.getNotes().size());
			for (String aNote : contact.getNotes()) {
				noteUri = Uri.withAppendedPath(rawContactUri, ContactsContract.Contacts.Data.CONTENT_DIRECTORY);
				values.clear();
				values.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Note.CONTENT_ITEM_TYPE);
				values.put(ContactsContract.CommonDataKinds.Note.NOTE, aNote);
				cr.insert(noteUri, values);
			}
		}

		if (contact.getImAddresses() != null) {
			Log.i("IM size", "" + contact.getImAddresses().size());
			for (IM aIM : contact.getImAddresses()) {
				imUri = Uri.withAppendedPath(rawContactUri, ContactsContract.Contacts.Data.CONTENT_DIRECTORY);
				values.clear();
				values.put(ContactsContract.CommonDataKinds.Im.PROTOCOL, aIM.getType());
				values.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE);
				values.put(ContactsContract.CommonDataKinds.Im.DATA, aIM.getName());
				cr.insert(imUri, values);
			}
		}

		if (contact.getOrganization() != null) {
			Log.i("Org size", "" + contact.getOrganization().size());
			for (Organization aORG : contact.getOrganization()) {
				orgUri = Uri.withAppendedPath(rawContactUri, ContactsContract.Contacts.Data.CONTENT_DIRECTORY);
				values.clear();
				values.put(ContactsContract.CommonDataKinds.Organization.TYPE, aORG.getType());
				values.put(ContactsContract.CommonDataKinds.Organization.TITLE, aORG.getPositions());// TODO:
				// check
				// again
				values.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE);
				values.put(ContactsContract.CommonDataKinds.Organization.DATA, aORG.getOrganization());
				cr.insert(orgUri, values);
			}
		}

		if (contact.getAddresses() != null) {
			Log.i("Org size", "" + contact.getAddresses().size());
			for (Address aAdd : contact.getAddresses()) {
				addressUri = Uri.withAppendedPath(rawContactUri, ContactsContract.Contacts.Data.CONTENT_DIRECTORY);
				values.clear();
				values.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE);
				if (aAdd.getCity() != null)
					values.put(ContactsContract.CommonDataKinds.StructuredPostal.CITY, aAdd.getCity());
				if (aAdd.getCountry() != null)
					values.put(ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY, aAdd.getCountry());
				if (aAdd.getPoBox() != null)
					values.put(ContactsContract.CommonDataKinds.StructuredPostal.POBOX, aAdd.getPoBox());
				if (aAdd.getPostalCode() != null)
					values.put(ContactsContract.CommonDataKinds.StructuredPostal.POSTCODE, aAdd.getPostalCode());
				if (aAdd.getStreet() != null)
					values.put(ContactsContract.CommonDataKinds.StructuredPostal.STREET, aAdd.getStreet());
				if (aAdd.getState() != null)
					values.put(ContactsContract.CommonDataKinds.StructuredPostal.REGION, aAdd.getState());
				values.put(ContactsContract.CommonDataKinds.StructuredPostal.TYPE, aAdd.getType());
				cr.insert(addressUri, values);
			}
		}
	}

	public boolean writeContact(ArrayList<Contact> contacts) {
		try {
			for (Contact contact : contacts) {
				writeContact(contact);
			}
			return true;
		} catch (Exception ex) {
			ex.printStackTrace();// show error in DDMS
			return false;
		}
	}
}
